package cn.maihe.elg.operation.centers.hymake.auth;

import cn.maihe.elg.operation.centers.hymake.auth.utils.SM2Util;
import cn.maihe.elg.operation.centers.hymake.config.HyMakeInfoConfig;
import cn.maihe.elg.operation.common.auth.Encryption;
import cn.maihe.elg.operation.config.ElgAuthConfig;
import cn.maihe.elg.operation.utils.RsaUtil;
import lombok.extern.slf4j.Slf4j;
import org.bouncycastle.util.encoders.Base64;
import org.springframework.util.Assert;

import java.nio.charset.StandardCharsets;

/**
 * @Description 海迈中心 加解密算法sm2 公钥加密 私钥解密
 * @Author WJH
 * @Date 2021/07/12
 */
@Slf4j
public class HyMakeEncryption implements Encryption {
    private final String sm2PubKey;
    private final String sm2PriKey;

    public HyMakeEncryption(ElgAuthConfig elgAuthConfig, HyMakeInfoConfig.CenterInfo centerInfo) {

        Assert.hasText(centerInfo.getSm2PubKey(), () -> centerInfo.getSysName() + "的sm2PubKey未配置");
        Assert.hasText(centerInfo.getSm2PriKey(), () -> centerInfo.getSysName() + "的sm2PriKey未配置");

        this.sm2PriKey = centerInfo.getSm2PriKey();
        this.sm2PubKey = centerInfo.getSm2PubKey();
    }


    /**
     * SM2 公钥加密
     *
     * @param unEncryptedData
     * @return
     */
    @Override
    public byte[] encrypt(byte[] unEncryptedData) {
        return encrypt(new String(unEncryptedData, StandardCharsets.UTF_8)).getBytes(StandardCharsets.UTF_8);
    }

    /**
     * 先sm4加密后再base64编码
     *
     * @param clearBizReqBody 明文
     * @return
     */
    public String encrypt(String clearBizReqBody) {
        Assert.hasText(clearBizReqBody, () -> "待加密数据不能为空");
        try {
            return SM2Util.encrypt(sm2PubKey, clearBizReqBody);
        } catch (Exception e) {
            throw new RuntimeException("加密异常:" + e.getMessage(), e);
        }
    }


    /**
     * sm2 私钥解密
     *
     * @param encryptedData
     * @return
     */
    @Override
    public byte[] decrypt(byte[] encryptedData) {
        return decrypt(new String(encryptedData, StandardCharsets.UTF_8)).getBytes(StandardCharsets.UTF_8);
    }

    /**
     * sm2 私钥解密
     *
     * @param encryptAndB64ReqBody
     * @return
     */
    public String decrypt(String encryptAndB64ReqBody) {
        Assert.hasText(encryptAndB64ReqBody, () -> "待解密数据不能为空");
        try {
            return SM2Util.decrypt(sm2PriKey, encryptAndB64ReqBody);
        } catch (Exception e) {
            throw new RuntimeException("解密失败:" + e.getMessage(), e);
        }
    }


    /**
     * RSA 公钥加密
     * @param clearBizReqBody 明文
     * @return
     */
    public String RSAEncrypt(String profiles,String clearBizReqBody) {
        Assert.hasText(clearBizReqBody, () -> "待加密数据不能为空");
        try {
            byte[] encryptedData;
            if("test".equals(profiles)){
                encryptedData = RsaUtil.encryptLargeData(RsaUtil.loadFromRSACer(sm2PubKey), clearBizReqBody.getBytes(StandardCharsets.UTF_8));
            }else {
                encryptedData = RsaUtil.encryptLargeData(RsaUtil.restorePublicKey(org.apache.commons.codec.binary.Base64.decodeBase64(sm2PubKey),
                        RsaUtil.KEY_ALGORITHM), clearBizReqBody.getBytes(StandardCharsets.UTF_8));
            }
            return Base64.toBase64String(encryptedData);
        } catch (Exception e) {
            throw new RuntimeException("加密异常:" + e.getMessage(), e);
        }
    }

    /**
     * RSA 私钥解密
     *
     * @param encryptAndB64ReqBody
     * @return
     */
    public String RSADecrypt(String profiles,String encryptAndB64ReqBody) {
        Assert.hasText(encryptAndB64ReqBody, () -> "待解密数据不能为空");
        try {
            byte[] decryptedData;
            if("test".equals(profiles)){
                decryptedData = RsaUtil.decryptLargeData(RsaUtil.loadFromRSAP12(sm2PriKey,"111111"), Base64.decode(encryptAndB64ReqBody));
            }else {
                decryptedData = RsaUtil.decryptLargeData(
                        RsaUtil.restorePrivateKey(org.apache.commons.codec.binary.Base64.decodeBase64(sm2PriKey), RsaUtil.KEY_ALGORITHM),
                        org.apache.commons.codec.binary.Base64.decodeBase64(encryptAndB64ReqBody));
            }
            return new String(decryptedData, StandardCharsets.UTF_8);
        } catch (Exception e) {
            throw new RuntimeException("解密失败:" + e.getMessage(), e);
        }
    }
}
